"""
定义一个带参数的装饰器

问题：
    你想定义一个可以接受参数的装饰器。
解决方案：
    们用一个例子详细阐述下接受参数的处理过程。
    假设你想写一个装饰器，给函数添加日志功能，同时允许用户指定日志的级别和其他的选项。
    核心思想：最外层的函数 logged() 接受参数并将它们作用在内部的装饰器函数上面。
        内层的函数 decorate() 接受一个函数作为参数，然后在函数上面放置一个包装器。
"""

import logging
from functools import wraps


def logged(level, name=None, message=None):
    def decorate(func):
        log_name = name if name else func.__module__
        log = logging.getLogger(log_name)
        log_msg = message if message else func.__name__

        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level, log_msg)
            return func(*args, *kwargs)

        return wrapper

    return decorate


@logged(logging.DEBUG)
def add(x, y):
    return x + y


@logged(logging.INFO, "user")
def say_hello(name):
    print("hello", name)


def use_logged():
    result = add(1, 1)
    print("1 + 1 = ", result)
    say_hello("Kevin")
    # 输出结果：
    """
    1 + 1 =  2
    hello Kevin
    """


if __name__ == '__main__':
    use_logged()
